using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace ZPod.MTG
{
	/// <summary>
	/// Mazo de juego
	/// </summary>
    
    [Serializable]
    [DataContract]
	public class Deck : IEnumerable<Card>
	{
		Random _rand = new Random();

		[DataMember]
		List<Card> _cards = new List<Card>();

		[DataMember]
		public List<Card> Cards
		{
			get
			{
				return new List<Card>(_cards);
			}
			set
			{
				_cards = new List<Card>(value);
			}
		}
		
		/// <summary>
		/// Crea un nuevo mazo vacio
		/// </summary>
		public Deck()
		{
		}
		
		/// <summary>
		/// Crea un nuevo mazo y lo inicializa con un archivo de cartas
		/// <para>
		/// El formato del archivo es el siguiente:
		/// </para>
		/// <para>
		/// </para>
		/// <para>
		/// Cantidad1 NombreCarta1
		/// </para>
		/// <para>
		/// Cantidad2 NombreCarta2
		/// </para>
		/// <para>
		/// # comentario
		/// </para>
		/// <para>
		/// Cantidad3 NombreCarta3
		/// </para>
		/// <para>
		/// ...
		/// </para>
		/// <para>
		/// CantidadN NombreCartaN
		/// </para>
		/// <para>
		/// </para>
		/// <para>
		/// ej:
		/// </para>
		/// <para>
		/// </para>
		/// <para>
		/// 10 Mountain
		/// </para>
		/// <para>
		/// # Esta carta es genial!
		/// </para>
		/// <para>
		/// 2 Mishra's Factory
		/// </para>
		/// </summary>
		/// <param name="fileName"></param>
		public Deck(string fileName)
		{
			using (StreamReader reader = new StreamReader(fileName))
			{
				
				List<String> cards = new List<String>();
				while (!reader.EndOfStream)
				{
					string line = reader.ReadLine().Trim();
					if (line.Length > 0 && !line.StartsWith("#")) // # para comentarios
					{
						cards.Add(line);
					}
				}
				
				LoadDeck(cards);
			}
		}
		
		/// <summary>
		/// Crea un nuevo mazo y lo inicializa con una lista de cartas
		/// </summary>
		/// <param name="cards"></param>
		public Deck(List<String> cards)
		{
			LoadDeck(cards);
		}
		
		/// <summary>
		/// Crea un mazo basado en un listado de cartas (Cantidad + Carta)
		/// </summary>
		/// <param name="cards"></param>
		private void LoadDeck(List<String> cards)
		{
			var orderedCards = new List<Card>();
			foreach (string cardData in cards)
			{
				int separatorPos = cardData.IndexOf(" ");
				int count = Int32.Parse(cardData.Substring(0, separatorPos));
				string name = cardData.Substring(separatorPos + 1);

				
				for (int i = 0; i < count; i++)
				{
					Card newCard = new Card(name);
					orderedCards.Add(newCard);
				}
			}

			_cards = new List<Card>(orderedCards);

			Shuffle();
		}

		/// <summary>
		/// Mezcla el mazo
		/// </summary>
		public void Shuffle()
		{
			var randomizedCards = new Card[_cards.Count];
			Random r = new Random();
			foreach (Card card in _cards)
			{
				int pos;
				do
				{
					pos = r.Next(0, _cards.Count);
				} while (randomizedCards[pos] != null);

				randomizedCards[pos] = card;
			}

			_cards = new List<Card>(randomizedCards);
		}
		
		/// <summary>
		/// Cantidad de cartas
		/// </summary>
		public int Count
		{
			get
			{
				return _cards.Count;
			}
		}

		public void PutOnTop(Card card)
		{
			var oldDeck = _cards;
			_cards = new List<Card>();
			_cards.Add(card);
			_cards.AddRange(oldDeck);
		}

		public void PutOnBack(Card card)
		{
			_cards.Add(card);
		}

		/// <summary>
		/// Saca la primera carta del mazo
		/// </summary>
		/// <returns></returns>
		public Card Take()
		{
			return Take(0);
		}

		/// <summary>
		/// Saca una carta del mazo
		/// </summary>
		/// <param name="index">Numero de carda</param>
		/// <returns></returns>
		public Card Take(int index)
		{
			Card card = _cards[index];
			_cards.RemoveAt(index);
			
			return card;
		}
		
		#region IEnumerable Members
		IEnumerator<Card> IEnumerable<Card>.GetEnumerator()
		{
			return Cards.GetEnumerator();
		}
		
		IEnumerator IEnumerable.GetEnumerator()
		{
			return Cards.GetEnumerator();
		}
		#endregion
	}
}
